#include "display.h"

#include <esp_err.h>
#include <esp_log.h>

#include <cstdlib>
#include <cstring>
#include <string>

#include "board.h"
#include "screenMain.h"

#define TAG "Display"

Display::Display() {
    // Notification timer
    esp_timer_create_args_t notification_timer_args = {
        .callback =
            [](void* arg) {
                Display* display = static_cast<Display*>(arg);
                DisplayLockGuard lock(display);
                lv_obj_clear_flag(ui_MainLabelStatus, LV_OBJ_FLAG_HIDDEN);
                lv_obj_add_flag(ui_MainLabelNotification, LV_OBJ_FLAG_HIDDEN);
            },
        .arg = this,
        .dispatch_method = ESP_TIMER_TASK,
        .name = "notification_timer",
        .skip_unhandled_events = false,
    };
    ESP_ERROR_CHECK(esp_timer_create(&notification_timer_args, &notification_timer_));

    // Update display timer
    esp_timer_create_args_t update_display_timer_args = {
        .callback =
            [](void* arg) {
                Display* display = static_cast<Display*>(arg);
                display->Update();
            },
        .arg = this,
        .dispatch_method = ESP_TIMER_TASK,
        .name = "display_update_timer",
        .skip_unhandled_events = true,
    };
    ESP_ERROR_CHECK(esp_timer_create(&update_display_timer_args, &update_timer_));
    ESP_ERROR_CHECK(esp_timer_start_periodic(update_timer_, 1000000));

    // Create a power management lock
    auto ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "display_update", &pm_lock_);
    if (ret == ESP_ERR_NOT_SUPPORTED) {
        ESP_LOGI(TAG, "Power management not supported");
    } else {
        ESP_ERROR_CHECK(ret);
    }
}

Display::~Display() {
    if (notification_timer_ != nullptr) {
        esp_timer_stop(notification_timer_);
        esp_timer_delete(notification_timer_);
    }
    if (update_timer_ != nullptr) {
        esp_timer_stop(update_timer_);
        esp_timer_delete(update_timer_);
    }
    if (pm_lock_ != nullptr) {
        esp_pm_lock_delete(pm_lock_);
    }
}

void Display::InitUI() {
    DisplayLockGuard lock(this);
    ScreenMain_init();
}

void Display::SetStatus(const char* status) {
    DisplayLockGuard lock(this);
    ScreenMain_setStatus(status);
}

void Display::ShowNotification(const std::string& notification, int duration_ms) { ShowNotification(notification.c_str(), duration_ms); }

void Display::ShowNotification(const char* notification, int duration_ms) {
    DisplayLockGuard lock(this);
    ESP_LOGI(TAG, "ShowNotification: %s", notification);
    ScreenMain_setNotification(notification);
}

void Display::Update() {
    auto& board = Board::GetInstance();

    esp_pm_lock_acquire(pm_lock_);
    // 更新电池图标
    int battery_level;
    bool charging, discharging;
    if (board.GetBatteryLevel(battery_level, charging, discharging)) {
        uint32_t battery_color = BAT_CRIT_COLOR;
        screen_main_bat_icon_t levels[] = {
            BAT_ICON_LEVEL_0,  // 0-24%
            BAT_ICON_LEVEL_1,  // 25-59%
            BAT_ICON_LEVEL_2,  // 40-74%
            BAT_ICON_LEVEL_3,  // 75-99%
            BAT_ICON_LEVEL_3,  // 100%
        };

        screen_main_bat_icon_t icon = levels[battery_level / 25];
        if (icon == BAT_ICON_LEVEL_0) {
            battery_color = BAT_CRIT_COLOR;
        } else if (icon == BAT_ICON_LEVEL_1) {
            battery_color = BAT_WARN_COLOR;
        } else {
            battery_color = BAT_SAFE_COLOR;
        }

        if (charging) {
            bat_anime = !bat_anime;
            if (icon != BAT_ICON_LEVEL_3) {
                icon = static_cast<screen_main_bat_icon_t>(icon + bat_anime);  // 强转回枚举类型
            }
        }
        DisplayLockGuard lock(this);
        ScreenMain_setBatIcon(icon, battery_color, battery_level);
    } else {
        ScreenMain_setBatIcon(BAT_ICON_NONE, 0, 0);
    }

    {
        // 更新WiFi图标
        DisplayLockGuard lock(this);
        auto wifi_strength = board.GetWiFiStrength();
        auto wifi_ssid = board.GetWiFiSSid();
        ScreenMain_setWiFiIcon(static_cast<screen_main_wifi_icon_t>(wifi_strength), wifi_ssid.c_str());
    }

    esp_pm_lock_release(pm_lock_);
}

void Display::SetEmotion(const char* emotion) {}

void Display::SetIcon(const char* icon) {}

void Display::SetChatMessage(const char* role, const char* content) {
    DisplayLockGuard lock(this);
    ESP_LOGI(TAG, "SetChatMessage: %s: %s", role, content);
    if (strcmp(role, "user") == 0) {
        ScreenMain_setRolerText(COMM_ROLER_USER, content);
    } else if (strcmp(role, "assistant") == 0) {
        ScreenMain_setRolerText(COMM_ROLER_ROBOT, content);
    } else if (strcmp(role, "system") == 0) {
        ScreenMain_setLoadingText(content);
    }
}

void Display::SetTheme(const std::string& theme_name) { ESP_LOGI(TAG, "SetTheme: %s", theme_name.c_str()); }

void Display::setMainPanel(screen_main_state_t state) {
    ESP_LOGI(TAG, "setMainPanel: %d", state);
    if (state == state_) {
        return;
    }
    DisplayLockGuard lock(this);
    state_ = state;
    ScreenMain_setMainPanel(state);
}
